#include <stdio.h> 
#include <stdlib.h>
#include <mach/vm_map.h>
#include <mach/mach_traps.h>


void* Search( mach_port_t port) ;

void error(char *msg) {
 printf("[!] error: %s\n",msg); exit(1);

}

mach_vm_address_t busca_endereco(vm_map_t  port);
int main(int ac, char **av) {
    vm_map_t port = MACH_PORT_NULL;
    kern_return_t ret = -1; 
    int tpid = -1;

    if(ac != 2) {
        printf("[+] usage: %s <pid>\n",av[0]);
        exit(1);
    }
   
    tpid =  atoi(av[1]);
    ret = task_for_pid(mach_task_self(),tpid, &port);
    if (ret!= KERN_SUCCESS) 
        error("nao foi possivel acessar memoria do jogo!");

    mach_vm_address_t endereco_dict = busca_endereco(port);

}
//==================================================================================================
// essa funcao percorre toda memoria do jogo procurando o endereco do vetor de comunicacao com addom
// este vetor possui valores padroes para os primeiros 5 elementos para ficar facil a busca
// =================================================================================================
mach_vm_address_t busca_endereco(vm_map_t  port){ 
    kern_return_t ret = -1; 
    mach_vm_address_t  endereco = 0x0;
    mach_vm_address_t  endereco_dict = 0x0;
    mach_vm_size_t   block_tam ;
    vm_region_basic_info_data_64_t info;
    mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64; // <-- isso eh imporante senao nao funciona direito
    mach_port_t object;

    int total_regioes=0;
    int terminou = 0;
    ret = KERN_SUCCESS; 
    
    while (mach_vm_region(port, &endereco, &block_tam, VM_REGION_BASIC_INFO_64, (vm_region_info_t)&info, &info_count, &object)== KERN_SUCCESS){
        int can_read = (info.protection & VM_PROT_READ);
        int can_write = (info.protection & VM_PROT_WRITE) >> 1;
        if (can_read && can_write){
           total_regioes+=1;
           unsigned char *bytes = malloc(block_tam);
                                
           if (bytes)
           {
                mach_vm_size_t outputSize = block_tam; // <---- isso eh importante senao nao fuciona direito
                if (mach_vm_read_overwrite(port, endereco, block_tam, (mach_vm_address_t)bytes, &outputSize) == KERN_SUCCESS)
                {
                        
                     long int i;
                     double v1,v2,v3,v4;
                     mach_vm_size_t v1z = sizeof(double);
                     //printf("comecou%d!\n\n",size);
                     // buscando por sequencia de bytes que representam o numero 2863311531.0 em notacao de ponto flutuante na memoria
                     for (i=0;i < outputSize-6;i+=1){
                          if (bytes[i]==96 && bytes[i+1]==85 && bytes[i+2]==85 && bytes[i+3]==85 && bytes[i+4]==229 && bytes[i+5]==65){
                              printf("entrei");
                              // o  -2 foi necessario pois pulamos os dois bytes do expoente do numero.
                              mach_vm_read_overwrite(port, endereco+i-2, v1z, (mach_vm_address_t)&v1, &v1z);
                                   
                              if (v1 == 2863311531){
                                   // ao encontrar o numero busca por 4 numeros  doubles especificos
                                   mach_vm_read_overwrite(port, endereco+i+16-2, v1z, (mach_vm_address_t)&v1, &v1z);
                                   mach_vm_read_overwrite(port, endereco+i+32-2, v1z, (mach_vm_address_t)&v2, &v1z);
                                   mach_vm_read_overwrite(port, endereco+i+48-2, v1z, (mach_vm_address_t)&v3, &v1z);
                                   mach_vm_read_overwrite(port, endereco+i+64-2, v1z, (mach_vm_address_t)&v4, &v1z);
                                   printf("%f,%f,%f,%f",v1,v2,v3,v4);        
                                   if ((v1 == 86331153) && (v2 == 633115) && (v3 == 3311) && (v4 == 31)  ){ 
                                       printf("achei! %f\n\n",v1);
                                       free(bytes);
                                       return endereco+i-2;
                                   }
                              }
                          }
                     }
                }
           }
           free(bytes);
        }
        
        endereco += block_tam;
    }

    printf("total de regioes buscadas: %d\n",total_regioes);
    return 0; 
}
